#include <iostream>
#include <memory>
#include <string>
#include <functional>
#include "ThreadPoll.hpp"
#include "Socket.hpp"
#include "Log.hpp"

namespace TcpServerModule
{

    using namespace SocketModule;
    using namespace LogModule;
    using namespace ThreadPollModule;
    const static uint16_t defaultport = 8889;
    const static std::string defaultip = "0.0.0.0";

    class TcpServer
    {
        using Handler_http_t = std::function<std::string(std::string)>;

    public:
        TcpServer(uint16_t port = defaultport, std::string ip = defaultip)
            : _socket(std::make_shared<TcpSocket>()), _port(port), _ip(ip)
        {
            _socket->CreateTcpSocket(_port, _ip);
        }

        void Service(std::shared_ptr<Socket> sock, uint16_t port, std::string ip, 
            Handler_http_t handlerfunc)
        {
            std::string req;
            if (sock->ReadMessage(&req))
            {
                LOG_DEBUG << "------------------------------------------";
                LOG_DEBUG << "-------     receive client     -----------";
                LOG_DEBUG << req;
                LOG_DEBUG << "------------------------------------------";
                std::string resp = handlerfunc(req);
                if(resp.empty())
                {
                    return;
                }
                LOG_DEBUG << "-------------------------------------" ;
                LOG_DEBUG << "-------   send to client    ---------" ;
                LOG_DEBUG << resp;
                LOG_DEBUG << "-------------------------------------" ;


                sock->WriteMessage(&resp);
            }
        }

        void Start(Handler_http_t hander)
        {
            while (true)
            {
                std::string ip;
                uint16_t port;
                std::shared_ptr<Socket> sock = _socket->AcceptConnect(&port, &ip);
                Service(sock, port, ip, hander);
                using packag_t = std::function<void()>;
                packag_t in = std::bind(&TcpServer::Service, this, sock, port, ip, hander);
                // 1. 取单例
                ThreadPoll *tp = ThreadPoll::GetInstance();

                // 2. 启动线程池
                tp->Start();
                tp->Enqueue(in);
            }
        }

    private:
        std::shared_ptr<Socket> _socket;
        uint16_t _port;
        std::string _ip;
    };
}